#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
自动化API测试框架入口

该模块是框架的入口点，提供命令行接口来运行测试。
"""

import argparse
import logging
import os
import sys
from typing import Dict, List, Any, Optional

from test_engine.test_executor import TestExecutor
from test_engine.test_loader import TestLoader
from test_engine.report_generator import ReportGenerator
from utils.logger import setup_logger, get_default_log_file
from config import Config


def parse_arguments():
    """
    解析命令行参数
    
    Returns:
        解析后的参数命名空间
    """
    parser = argparse.ArgumentParser(description='基于Swagger的自动化API测试框架')
    
    # Swagger文档参数
    swagger_group = parser.add_argument_group('Swagger文档')
    swagger_group.add_argument('--swagger-url', dest='swagger_url',
                            help='Swagger文档URL')
    swagger_group.add_argument('--swagger-file', dest='swagger_file',
                            help='Swagger文档本地文件路径')
    
    # 测试用例参数
    test_group = parser.add_argument_group('测试用例')
    test_group.add_argument('--test-case', dest='test_case',
                          help='单个测试用例文件路径')
    test_group.add_argument('--test-suite', dest='test_suite',
                          help='测试套件文件路径')
    test_group.add_argument('--test-dir', dest='test_dir',
                          help='测试用例目录')
    
    # 环境参数
    env_group = parser.add_argument_group('环境配置')
    env_group.add_argument('--env', dest='environment',
                         help='运行环境，可选值：dev, test, prod')
    env_group.add_argument('--config', dest='config_file',
                         help='配置文件路径')
    
    # 报告参数
    report_group = parser.add_argument_group('测试报告')
    report_group.add_argument('--report-dir', dest='report_dir',
                            help='测试报告输出目录')
    report_group.add_argument('--report-format', dest='report_format',
                            choices=['html', 'json', 'text'],
                            help='测试报告格式')
    
    # 日志参数
    log_group = parser.add_argument_group('日志配置')
    log_group.add_argument('--log-level', dest='log_level',
                         choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
                         help='日志级别')
    log_group.add_argument('--log-file', dest='log_file',
                         help='日志文件路径')
    
    # 模拟数据生成参数
    mock_group = parser.add_argument_group('模拟数据生成')
    mock_group.add_argument('--auto-mock', dest='auto_generate_mock_data',
                          action='store_true', default=None,
                          help='自动生成模拟数据')
    mock_group.add_argument('--no-auto-mock', dest='auto_generate_mock_data',
                          action='store_false', default=None,
                          help='禁用自动生成模拟数据')
    mock_group.add_argument('--confirm-mock', dest='confirm_mock_data',
                          action='store_true', default=None,
                          help='启用模拟数据确认')
    mock_group.add_argument('--no-confirm-mock', dest='confirm_mock_data',
                          action='store_false', default=None,
                          help='禁用模拟数据确认')
    
    # 更新测试用例参数
    update_group = parser.add_argument_group('更新测试用例配置')
    update_group.add_argument('--update-test-case', dest='update_test_case',
                             help='使用模拟数据更新指定的测试用例文件')
    update_group.add_argument('--output-path', dest='output_path',
                             help='指定更新后的测试用例输出路径，如果不指定则覆盖原文件')
    
    return parser.parse_args()


def update_config_from_args(args):
    """
    根据命令行参数更新配置
    
    Args:
        args: 命令行参数命名空间
    """
    # 加载配置文件
    if args.config_file:
        Config.from_file(args.config_file)
    
    # 更新Swagger配置
    if args.swagger_url:
        Config.SWAGGER_URL = args.swagger_url
    if args.swagger_file:
        Config.SWAGGER_FILE = args.swagger_file
    
    # 更新环境配置
    if args.environment:
        Config.CURRENT_ENV = args.environment
    
    # 更新报告配置
    if args.report_dir:
        Config.REPORT_DIR = args.report_dir
    if args.report_format:
        Config.REPORT_FORMAT = args.report_format
    
    # 更新日志配置
    if args.log_level:
        Config.LOG_LEVEL = args.log_level
        
    # 更新模拟数据生成配置
    if args.auto_generate_mock_data is not None:
        Config.AUTO_GENERATE_MOCK_DATA = args.auto_generate_mock_data


def main():
    """
    主函数
    """
    # 解析命令行参数
    args = parse_arguments()
    
    # 更新配置
    update_config_from_args(args)
    
    # 设置日志
    log_file = args.log_file or get_default_log_file()
    logger = setup_logger(Config.LOG_LEVEL, log_file)
    
    logger.info("启动自动化API测试框架")
    logger.info(f"当前环境: {Config.CURRENT_ENV}")
    
    # 检查是否是更新测试用例模式
    if args.update_test_case:
        update_test_case_with_mock_data(args.update_test_case, args.output_path, not args.no_confirm_mock)
        return
    
    try:
        # 初始化测试执行器
        logger.info("初始化测试执行器")
        test_executor = TestExecutor(auto_generate_mock_data=Config.AUTO_GENERATE_MOCK_DATA, confirm_mock_data=Config.CONFIRM_MOCK_DATA)
        
        # 初始化测试用例加载器
        logger.info("初始化测试用例加载器")
        test_loader = TestLoader()
        
        # 加载测试用例
        test_cases = []
        
        if args.test_case:
            logger.info(f"加载单个测试用例: {args.test_case}")
            test_case = test_loader.load_test_case(args.test_case)
            test_cases.append(test_case)
        elif args.test_suite:
            logger.info(f"加载测试套件: {args.test_suite}")
            test_cases = test_loader.load_test_suite(args.test_suite)
        elif args.test_dir:
            logger.info(f"从目录加载测试用例: {args.test_dir}")
            test_cases = test_loader.load_test_cases_from_directory(args.test_dir)
        else:
            # 默认从测试用例目录加载
            test_dir = Config.TEST_CASE_DIR
            if os.path.exists(test_dir) and os.path.isdir(test_dir):
                logger.info(f"从默认目录加载测试用例: {test_dir}")
                test_cases = test_loader.load_test_cases_from_directory(test_dir)
            else:
                logger.error(f"测试用例目录不存在: {test_dir}")
                sys.exit(1)
        
        if not test_cases:
            logger.error("未找到测试用例")
            sys.exit(1)
            
        logger.info(f"加载了 {len(test_cases)} 个测试用例")
        
        # 执行测试用例
        logger.info("开始执行测试用例")
        test_results = []
        
        for test_case in test_cases:
            logger.info(f"执行测试用例: {test_case['name']}")
            result = test_executor.execute_test_case(test_case)
            test_results.append(result)
        
        # 生成测试报告
        logger.info("生成测试报告")
        report_generator = ReportGenerator(Config.REPORT_DIR)
        report_file = report_generator.generate_report(test_results, Config.REPORT_FORMAT)
        
        # 打印测试摘要
        report_generator.print_summary(test_results)
        
        logger.info(f"测试报告已生成: {report_file}")
        logger.info("测试执行完成")
        
    except Exception as e:
        logger.error(f"测试执行过程中发生错误: {str(e)}", exc_info=True)
        sys.exit(1)


def update_test_case_with_mock_data(test_case_path: str, output_path: str = None, confirm: bool = True):
    """使用模拟数据更新测试用例文件"""
    logger = logging.getLogger(__name__)
    logger.info(f"使用模拟数据更新测试用例文件: {test_case_path}")
    
    # 初始化模拟数据生成器
    mock_data_generator = MockDataGenerator()
    
    # 更新测试用例
    success, message, updated_data = mock_data_generator.update_test_case_with_mock_data(test_case_path, output_path, confirm)
    
    if success and confirm and updated_data:
        # 显示更新的数据
        confirmation_message = mock_data_generator.format_mock_data_for_confirmation(updated_data)
        print("\n" + confirmation_message)
        
        # 请求用户确认
        while True:
            user_input = input("\n是否保存这些更新? (y/n): ").strip().lower()
            if user_input in ['y', 'yes']:
                # 确认并保存更新
                save_success, save_message = mock_data_generator.confirm_and_save_updates(test_case_path, updated_data, output_path)
                if save_success:
                    logger.info(save_message)
                    print(f"\n✅ {save_message}")
                else:
                    logger.error(save_message)
                    print(f"\n❌ {save_message}")
                break
            elif user_input in ['n', 'no']:
                logger.info("用户取消了更新")
                print("\n已取消更新")
                break
            else:
                print("无效的输入，请输入 y 或 n")
    else:
        # 直接显示结果消息
        if success:
            logger.info(message)
            print(f"\n✅ {message}")
        else:
            logger.error(message)
            print(f"\n❌ {message}")

if __name__ == '__main__':
    main()